package com.kairos.motion
{
	import com.kairos.engine.MockRTBeacon;
	
	import flash.display.MovieClip;
	
	import flexunit.framework.TestCase;
	import com.bourre.structures.Range;
	import com.bourre.log.PixlibDebug;
	import mx.validators.ValidationResult;
	import com.bourre.commands.MockASyncCommandListener;
	import com.kairos.log.KairosDebug;

	public class AdvancedMovieClipRTTest extends TestCase
	{
		[Embed(source="anim.swf",symbol="Animation")] 
			private var Animation : Class;
		
		private var _mc : MovieClip;
		private var _mcrt : MockAdvancedMovieClipRT;
		private var _oB : MockRTBeacon;
		
		public override function setUp() : void
		{
			_mc = new Animation();
			_mcrt = new MockAdvancedMovieClipRT ( _mc );
			_oB = MockRTBeacon.getInstance();
			_oB.setStep( 25 );
		}
		
		public override function tearDown():void
		{
			_mcrt.stop();
		}
		
		public function testConstruct () : void 
		{
			assertNotNull ( "AdvancedMovieClipRT constructor returns null", _mcrt );
			assertNotNull ( _mcrt + ".getMovieClip() return null after creation", _mcrt.getMovieClip() );
			assertEquals ( _mcrt + ".getFramerate() don't return the default value", 40, _mcrt.getFramerate() );
			assertNotNull ( _mcrt + ".getRange() return null", _mcrt.getRange() );
			assertEquals ( _mcrt + ".getLoopCount() don't return 0", 0, _mcrt.getLoopCount() );
		}
		
		public function testRun () : void 
		{
			//KairosDebug.DEBUG( "RUNNING ----------------------------------------" );
			
			var n : Number = 0;
			
			_mcrt.setLoopCount( 1 );
			_mcrt.start();
			
			while( _mcrt.isRunning() && n < 500 ) 
			{
				_oB.onTick( null );
				n++;
			}
			
			assertFalse ( _mcrt + ".isRunning() haven't finish its run", _mcrt.isRunning() );	
			assertEquals ( _mcrt + " haven't realized the animation in the time", 19, n );
			assertEquals ( "", 20, _mc.currentFrame );
		}
		public function testRunWithBigStep () : void 
		{
			//KairosDebug.DEBUG( "RUNNING BIG STEP----------------------------------------" );
			
			var n : Number = 0;
			_oB.setStep( 100 );
			_mcrt.setLoopCount( 1 );
			_mcrt.start();
			
			while( _mcrt.isRunning() && n < 500 ) 
			{
				_oB.onTick( null );
				n++;
			}
			
			assertFalse ( _mcrt + ".isRunning() haven't finish its run", _mcrt.isRunning() );	
			assertEquals ( _mcrt + " haven't realized the animation in the time", 5, n );
			assertEquals ( "", 20, _mc.currentFrame );
		}
		public function testRunLoop () : void
		{
			//KairosDebug.DEBUG( "RUNNING LOOP ----------------------------------------" );
			
			var n : Number = 0;	
			
			_mcrt.setLoopCount( 4 );			
			_mcrt.start();	
			
			while( _mcrt.isRunning() && n < 500 ) 
			{
				_oB.onTick( null );
				n++;
			}
			
			assertFalse ( _mcrt + ".isRunning() haven't finish its run", _mcrt.isRunning() );	
			assertEquals ( _mcrt + " haven't realized the animation in the time", 79, n );
			assertEquals ( "", 20, _mc.currentFrame );
		}
		
		public function testRunLoopWithBigStep () : void
		{
		
			//KairosDebug.DEBUG( "RUNNING LOOP BIG STEP ----------------------------------------" );
			
			var n : Number = 0;	
			_oB.setStep( 100 );			
			_mcrt.setLoopCount( 4 );
			_mcrt.start();

			while( _mcrt.isRunning() && n < 500 ) 
			{
				_oB.onTick( null );
				n++;
			}
			
			assertFalse ( _mcrt + ".isRunning() haven't finish its run", _mcrt.isRunning() );	
			assertEquals ( _mcrt + " haven't realized the animation in the time", 20, n );
			assertEquals ( "", 20, _mc.currentFrame );
			
		}
		
		public function testRunReversed () : void 
		{
			//KairosDebug.DEBUG( "REVERSED ----------------------------------------" );
			
			var n : Number = 0;
			
			_mcrt.reverse();
			_mcrt.reset();
			_mcrt.setLoopCount( 1 );
			_mcrt.start();
			
			while( _mcrt.isRunning() && n < 500 ) 
			{
				_oB.onTick( null );
				n++;
			}
			
			assertFalse ( _mcrt + ".isRunning() (reversed) haven't finish its run", _mcrt.isRunning() );	
			assertEquals ( _mcrt + " haven't realized the animation (reversed) in the time", 19, n );
			assertEquals ( "", 1, _mc.currentFrame );
		}
		public function testRunReversedLoop () : void
		{
			//KairosDebug.DEBUG( "REVERSED LOOP ----------------------------------------" );
			
			var n : Number = 0;	
			_mcrt.reverse();	
			_mcrt.reset();
			_mcrt.setLoopCount( 4 );	
			_mcrt.start();
			
			while( _mcrt.isRunning() && n < 500 ) 
			{
				_oB.onTick( null );
				n++;
			}
			
			assertFalse ( _mcrt + ".isRunning() (reversed) haven't finish its run", _mcrt.isRunning() );	
			assertEquals ( _mcrt + " haven't realized the animation (reversed) in the time", 79, n );
			assertEquals ( "", 1, _mc.currentFrame );
		}
		public function testRunReversedLoopWithBigStep () : void
		{
			//KairosDebug.DEBUG( "REVERSED LOOP BIG STEP----------------------------------------" );
			
			_oB.setStep( 100 );
			var n : Number = 0;			
			_mcrt.reverse();	
			_mcrt.reset();
			_mcrt.setLoopCount( 4 );	
			_mcrt.start();
			
			while( _mcrt.isRunning() && n < 500 ) 
			{
				_oB.onTick( null );
				n++;
			}
			
			assertFalse ( _mcrt + ".isRunning() (reversed) haven't finish its run", _mcrt.isRunning() );	
			assertEquals ( _mcrt + " haven't realized the animation (reversed) in the time", 20, n );
			assertEquals ( "", 1, _mc.currentFrame );
		}		
		public function testRunInRange () : void 
		{
			//KairosDebug.DEBUG( "RANGE ----------------------------------------" );
			
			var n : Number = 0;
			
			_mcrt.setLoopCount( 4 );
			_mcrt.setRange( new Range ( 11, 20 ) );
			_mcrt.start();
			
			while( _mcrt.isRunning() && n < 500 ) 
			{
				_oB.onTick( null );
				n++;
			}
			
			assertFalse ( _mcrt + ".isRunning() haven't finish is run", _mcrt.isRunning() );	
			assertEquals ( _mcrt + " haven't realized the animation in the time", 39, n );	
		}
		
		public function testRunInRangeReversed () : void 
		{
			//KairosDebug.DEBUG( "RANGE ----------------------------------------" );
			
			var n : Number = 0;
			
			var mc : MovieClip = new Animation();
			var mcrt : MockAdvancedMovieClipRT = new MockAdvancedMovieClipRT ( mc, 40, 4, new Range( 11, 20 ), true );

			assertEquals ( mcrt + " start frame is not the last frame in the range", 20, mc.currentFrame );

			mcrt.start();
			
			
			while( mcrt.isRunning() && n < 500 ) 
			{
				KairosDebug.DEBUG( mc.currentFrame );
				_oB.onTick( null );
				n++;
			}
			assertEquals ( mcrt + " end frame is not the first frame in the range", 11, mc.currentFrame );
			assertFalse ( mcrt + ".isRunning() haven't finish is run", mcrt.isRunning() );	
			assertEquals ( mcrt + " haven't realized the animation in the time", 39, n );	
		}
		
		public function testRunInMinimalRange() : void
		{
			//KairosDebug.DEBUG( "RANGE MINIMUM----------------------------------------" );
			
			var n: Number = 0;
			
			_mcrt.setLoopCount( 4 );
			_mcrt.setRange( new Range ( 11, 12 ) );
			_mcrt.start();
			
			while( _mcrt.isRunning() && n < 20 ) 
			{
				_oB.onTick( null );
				n++;
			}
			
			assertFalse ( _mcrt + ".isRunning() haven't finish is run", _mcrt.isRunning() );	
			assertEquals ( _mcrt + " haven't realized the animation in the time", 7, n );	
		}
		
		public function testRunEndLess () : void 
		{
			//KairosDebug.DEBUG( " RUNNING ENDLESS ----------------------------------------" );
			
			var n : Number = 0;

			_mcrt.start();
			
			while( n < 500 ) 
			{
				_oB.onTick( null );
				n++;
			}
			assertTrue ( _mcrt + ".isRunning() have finish its run", _mcrt.isRunning() );		
		}	
		public function testSetLoopCount () : void
		{
			_mcrt.setLoopCount ( 20 );
			
			assertEquals ( _mcrt + ".setLoopCount() failed to defines the new count", 20, _mcrt.getLoopCount() );
		}
		public function testSetMovieClip () : void 
		{
			var m : MovieClip = new MovieClip ();
			_mcrt.setMovieClip( m );
			
			assertEquals ( _mcrt + ".setMovieClip() failed to add the new MovieClip", m, _mcrt.getMovieClip() );
			
			var errorOccurs : Boolean = false;
			try 
			{
				_mcrt.setMovieClip( null );
			}
			catch( e : Error )
			{
				errorOccurs = true;
			}
			assertTrue ( _mcrt + ".setMovieClip() don't failed when passing a null object", errorOccurs );
		}
		
		public function testSetFrameRate () : void 
		{
			_mcrt.setFramerate( 80 );
			
			assertEquals ( _mcrt + ".setFramerate() failed to set the new framerate", 80, _mcrt.getFramerate() );
			
			var errorOccurs : Boolean = false;
		}
		public function testSetRange () : void
		{
			_mcrt.setRange ();
			assertNotNull ( _mcrt + ".getRange() return null", _mcrt.getRange() );
			assertEquals ( _mcrt + ".getRange().min don't return 1", 1, _mcrt.getRange().min );
			assertEquals ( _mcrt + ".getRange().max don't return 20", 20, _mcrt.getRange().max );
			
			_mcrt.setRange ( new Range ( 2,8 ) );
			assertNotNull ( _mcrt + ".getRange() return null", _mcrt.getRange() );
			assertEquals ( _mcrt + ".getRange().min don't return 2", 2, _mcrt.getRange().min );
			assertEquals ( _mcrt + ".getRange().max don't return 8", 8, _mcrt.getRange().max );
			
			_mcrt.setRange ( new Range ( -2,58 ) );
			assertNotNull ( _mcrt + ".getRange() return null", _mcrt.getRange() );
			assertEquals ( _mcrt + ".getRange().min don't return 1", 1, _mcrt.getRange().min );
			assertEquals ( _mcrt + ".getRange().max don't return 20", 20, _mcrt.getRange().max );
			
			var errorOccurs : Boolean = false;
			try
			{
				_mcrt.setRange( new Range ( 11, 11 ) );
			}
			catch( e : Error )
			{
				errorOccurs = true;
			}
			assertTrue ( _mcrt + "don't failed when specifying a range of length 0" );
		}
		public function testReverse () : void 
		{
			var a : Array = [6, 2, 6, 2, 6];
			var n : Number = 0;
			
			_oB.setStep( 100 );
			
			_mcrt.setLooping( false );
			_mcrt.gotoAndStop( 2 );
			_mcrt.start();
			
			while( n <= 4 ) 
			{
				_oB.onTick( null );
				assertEquals ( _mcrt + ".reverse() failed to change the way of the animation", a[n], _mc.currentFrame );
				_mcrt.reverse();
				n++;
			}
		}
		
		public function testReset () : void 
		{
			var a : Array = [5, 5, 5, 5, 5];
			var n : Number = 0;
			
			_oB.setStep( 100 );
			
			_mcrt.setLooping( false );
			_mcrt.start();
			
			while( n <= 4 ) 
			{
				_oB.onTick( null );
				assertEquals ( _mcrt + ".reset() failed to place the frame to start", a[n], _mc.currentFrame );
				_mcrt.reset();
				n++;
			}
		}
		
		public function testShowHide () : void 
		{
			assertTrue( _mc + ".visible isn't true at creation", _mc.visible );
			
			_mcrt.hide();
			
			assertFalse( _mc + ".visible isn't false after a hide call", _mc.visible );
			
			_mcrt.show();
			
			assertTrue( _mc + ".visible isn't true after a show call", _mc.visible );
		}
		
		
		public function testAsyncBehavior () : void 
		{
			var m : MockASyncCommandListener = new MockASyncCommandListener();
			
			_mcrt.setLoopCount( 1 );
			_mcrt.addASyncCommandListener( m );
			_mcrt.start();
			
			while( _mcrt.isRunning() ) 
			{
				_oB.onTick( null );
			}
			assertTrue ( _mcrt + " haven't dispatch the onCommandEnd event", m.called );
		}
		
		public function testGotoAndPlay () : void 
		{
			_mcrt.gotoAndPlay( 10 );
			assertTrue ( _mcrt + ".isRunning() return false after a gotoAndPlay() call", _mcrt.isRunning() );
			assertEquals ( _mcrt + ".gotoAndPlay() failed to move the playhead", 10, _mc.currentFrame );
			
			_mcrt.gotoAndPlay( "lastLabel" );
			assertTrue ( _mcrt + ".isRunning() return false after a second gotoAndPlay() call", _mcrt.isRunning() );
			assertEquals ( _mcrt + ".gotoAndPlay() failed to move the playhead to the label", 20, _mc.currentFrame );
			
			var b : Boolean;
			
			b = false;
			_mcrt.stop();
			try
			{
				_mcrt.gotoAndPlay( true );
			}
			catch( e : Error )
			{
				b = true;
			}
			assertTrue ( _mcrt + ".gotoAndPlay() don't failed with a boolean argument", b );
			
			b = false;
			_mcrt.stop();
			try
			{
				_mcrt.gotoAndPlay( 0.5 );
			}
			catch( e : Error )
			{
				b = true;
			}
			assertTrue ( _mcrt + ".gotoAndPlay() don't failed with a float argument", b );
			
			assertEquals ( _mcrt + ".gotoAndPlay() move the playhead while passing an invalid label", 20, _mc.currentFrame );
		}
		
		public function testGotoAndStop () : void 
		{
			_mcrt.start()
			
			_mcrt.gotoAndStop( 10 );
			assertFalse ( _mcrt + ".isRunning() return true after a gotoAndStop() call", _mcrt.isRunning() );
			assertEquals ( _mcrt + ".gotoAndStop() failed to move the playhead", 10, _mc.currentFrame );
			
			_mcrt.gotoAndStop( "lastLabel" );
			assertFalse ( _mcrt + ".isRunning() return false after a second gotoAndStop() call", _mcrt.isRunning() );
			assertEquals ( _mcrt + ".gotoAndStop() failed to move the playhead to the label", 20, _mc.currentFrame );
			
			var b : Boolean;
			
			b = false;
			_mcrt.start();
			try
			{
				_mcrt.gotoAndStop( true );
			}
			catch( e : Error )
			{
				b = true;
			}
			assertTrue ( _mcrt + ".gotoAndStop() don't failed with a boolean argument", b );
			
			b = false;
			_mcrt.start();
			try
			{
				_mcrt.gotoAndStop( 0.5 );
			}
			catch( e : Error )
			{
				b = true;
			}
			assertTrue ( _mcrt + ".gotoAndStop() don't failed with a float argument", b );
			
			assertEquals ( _mcrt + ".gotoAndStop() move the playhead while passing an invalid label", 20, _mc.currentFrame );
		}		
		
		public function testLocalSpeedGetterSetter () : void 
		{
			var errorOccurs : Boolean;
			
			errorOccurs = false;
			try
			{
				_mcrt.setLocalSpeed( 0 );
			}
			catch ( e : Error )
			{
				errorOccurs = true;
			}
			
			assertTrue( _mcrt + ".setLocalSpeed() don't failed with a value of 0", errorOccurs );
			assertEquals ( _mcrt + ".setLocalSpeed() with an invalid argument have modify the local speed", 1, _mcrt.getLocalSpeed() );
			
			errorOccurs = false;
			try
			{
				_mcrt.setLocalSpeed( -1 );
			}
			catch ( e : Error )
			{
				errorOccurs = true;
			}
			
			assertTrue( _mcrt + ".setLocalSpeed() don't failed with a negative value", errorOccurs );
			assertEquals ( _mcrt + ".setLocalSpeed() with an invalid argument have modify the local speed", 1, _mcrt.getLocalSpeed() );
			
			
			_mcrt.setLocalSpeed( 2 );
			assertEquals ( _mcrt + ".setLocalSpeed() failed to change the local speed", 2, _mcrt.getLocalSpeed() );
			
		}
		public function testTickBeaconGetterSetter () : void 
		{
			var errorOccurs : Boolean;
			
			errorOccurs = false;
			try
			{
				_mcrt.setTickBeacon( null );
			}
			catch ( e : Error )
			{
				errorOccurs = true;
			}
			
			assertTrue( _mcrt + ".setTickBeacon() don't failed with a null beacon", errorOccurs );
			
			var beacon : MockRTBeacon = new MockRTBeacon ();
			
			_mcrt.setTickBeacon( beacon );
			
			assertEquals ( _mcrt + ".setTickBeacon() failed to set the new beacon", beacon, _mcrt.getTickBeacon() );
		}
		public function testStartStop() : void
		{
			_mcrt.start ();
			
			_oB.onTick( null );
			assertTrue( _mcrt + ".isRunning() return false after a call of start", _mcrt.isRunning() );
			
			_mcrt.stop ();
			
			assertFalse( _mcrt + ".isRunning() return true after a call of sop", _mcrt.isRunning() );
		}
		
		public function testStartAlias () : void
		{
			_mcrt.execute ();
			assertTrue( _mcrt + ".isRunning() return false after a call of execute", _mcrt.isRunning() );
			_mcrt.stop ();
			
			_mcrt.play ();
			assertTrue( _mcrt + ".isRunning() return false after a call of play", _mcrt.isRunning() );
			_mcrt.stop ();
		}
	}
}